home *** CD-ROM | disk | FTP | other *** search
/ Dr. Windows 3 / dr win3.zip / dr win3 / WINPROGS / WUNZ20SR.ZIP / STATUS.C < prev    next >
C/C++ Source or Header  |  1993-06-07  |  28KB  |  745 lines

  1. /* Status.c -- the status module of WizUnZip
  2.  * Robert Heath. 1991.
  3.  */
  4.  
  5. #include <sys\types.h>
  6. #include <sys\stat.h>
  7. #include <time.h>                
  8. #include <string.h>
  9. #include <ctype.h>
  10. #include <io.h>
  11. #include <stdio.h>
  12. #include <stdarg.h>
  13. #include "wizunzip.h"
  14. #include "unzip.h"
  15.  
  16. #define STATUS_INCREMENT    512 /* incremental status data size     */
  17. #define MAX_H_CHARS 160         /* max horizontal chars.            */
  18.  
  19. #define MAX_INDEX_ENTRIES 16    /* Message Window index max entries */
  20.  
  21. #define cchBufferMax 0xffffL    /* max Message Buffer size. Must fit 
  22.                                  * within one memory segment!       */
  23.  
  24. #define cchTextOutMax 0x7fffL /* max no. bytes TextOut() accepts */
  25.  
  26. #define STDIO_BUF_SIZE (FILNAMSIZ+LONG_FORM_FNAME_INX) /* buffer size during printf or fprintf */
  27.  
  28. static short yClient;               /* height of client area */
  29. static short nVscrollPos = 0;       /* scroll position of mesg. window  */
  30. static short nNumLines = 0;         /* number of lines in buffer */
  31. static short nVscrollMax;           /* max scroll position of mesg. window  */
  32. static DWORD dwStatusSize = 0L;     /* status data size */
  33. static DWORD dwBufferSize = 0L;     /* Status buffer size.  Never 
  34.                                        exceeds cchBufferMax     */
  35. static HANDLE hStatusBuffer;        /* global mesg. handle  */
  36. static DWORD rgidwMsgWin[MAX_INDEX_ENTRIES]; /* max index entries   */
  37. static short    cMsgWinEntries;         /* no. active index entries, with
  38.                                        MAX_INDEX_ENTRIES as its max. 
  39.                                        When set to 0, it's time to 
  40.                                        re-index.*/
  41.  
  42. static short nLinesPerEntry;        /* lines per index entry    */
  43.  
  44. /* displayed when buffer shouldn't grow or can't grow                   */
  45. static char __based(__segname("STRINGS_TEXT")) szClearBufferMsg[] =     
  46.             "Clearing Status window to make room for more information.";
  47.  
  48. /* displayed when buffer shouldn't grow or can't grow                   */
  49. static char __based(__segname("STRINGS_TEXT")) szCantClipboard[] =     
  50.             "Cannot get enough memory to copy Status window to clipboard.";
  51.  
  52. struct KeyEntry
  53. {
  54.     WORD    wVirtKey;
  55.     BOOL    bCntl;
  56.     WORD    wMessage;
  57.     WORD    wRequest;
  58. } __based(__segname("STRINGS_TEXT")) KeyTable[] = 
  59. {
  60.     /* vertical scroll control */
  61.     {VK_HOME,   TRUE,   WM_VSCROLL, SB_TOP },
  62.     {VK_END,    TRUE,   WM_VSCROLL, SB_BOTTOM },
  63.     {VK_PRIOR,  FALSE,  WM_VSCROLL, SB_PAGEUP },
  64.     {VK_NEXT,   FALSE,  WM_VSCROLL, SB_PAGEDOWN },
  65.     {VK_UP,     FALSE,  WM_VSCROLL, SB_LINEUP },
  66.     {VK_DOWN,   FALSE,  WM_VSCROLL, SB_LINEDOWN },
  67.  
  68.     /* horizontal scroll control */
  69.     {VK_HOME,   FALSE,  WM_HSCROLL, SB_TOP },
  70.     {VK_END,    FALSE,  WM_HSCROLL, SB_BOTTOM },
  71.     {VK_PRIOR,  TRUE,   WM_HSCROLL, SB_PAGEUP },
  72.     {VK_NEXT,   TRUE,   WM_HSCROLL, SB_PAGEDOWN },
  73.     {VK_LEFT,   FALSE,  WM_HSCROLL, SB_LINEUP },
  74.     {VK_RIGHT,  FALSE,  WM_HSCROLL, SB_LINEDOWN },
  75. } ;
  76.  
  77. #define NUMKEYS (sizeof(KeyTable)/sizeof(struct KeyEntry)) 
  78.  
  79. /* Forward Refs
  80.  */
  81. static void FreeStatusLog(void);
  82.  
  83. /* Globals */
  84. BOOL bRealTimeMsgUpdate = TRUE; /* update messages window in real-time.
  85.                                  * Reset by callers when update can be
  86.                                  * be deferred.
  87.                                  */
  88. BOOL gfCancelDisplay = FALSE;    /* cancel display if got in over our heads */
  89.  
  90. /* Clears status buffer. Frees buffer.
  91.  */
  92. static void FreeStatusLog(void)
  93. {
  94.     if (hStatusBuffer)
  95.     {
  96.         GlobalFree(hStatusBuffer);
  97.         hStatusBuffer = (HANDLE)0;
  98.     }
  99.     dwStatusSize = 0L;      /* status data size             */
  100.     dwBufferSize = 0L;      /* status buffer size           */
  101.     nNumLines = 0;          /* number of lines in buffer    */
  102.     nVscrollMax = 1;
  103.     SetScrollRange(hWndStatus, SB_VERT, 0, 1, FALSE);
  104.     nVscrollPos = 0;
  105.     SetScrollPos(hWndStatus, SB_VERT, nVscrollPos, TRUE);
  106. }
  107.  
  108. /* Update Message Window Position is called after adding 
  109.  * a number of lines to the message window without updating it.
  110.  * The function invalidates then updates the window.
  111.  */
  112. void UpdateMsgWndPos(void)
  113. {
  114.     nVscrollPos = max(0,(nNumLines-cLinesMessageWin+1));     /* set position to next to last line   */
  115.     SetScrollPos(hWndStatus, SB_VERT, nVscrollPos, TRUE);
  116.     InvalidateRect(hWndStatus, NULL, TRUE);
  117.     UpdateWindow(hWndStatus);
  118. }
  119.  
  120. /* Set Status Top Window Position is called after adding 
  121.  * a number of lines to the message window without updating it.
  122.  * Unlike UpdateMsgWndPos() above, this function sets the
  123.  * status window position to the top.
  124.  * The function invalidates then updates the window.
  125.  */
  126. void SetStatusTopWndPos(void)
  127. {
  128.     nVscrollPos = 0;     /* set position to next to top line   */
  129.     SetScrollPos(hWndStatus, SB_VERT, nVscrollPos, TRUE);
  130.     InvalidateRect(hWndStatus, NULL, TRUE);
  131.     UpdateWindow(hWndStatus);
  132. }
  133.  
  134. /* Add message line (or part of a line) to the global status buffer
  135.  * that is the contents of the Message Window.
  136.  * Assumes that global data is unlocked when called.
  137.  */
  138. void WriteStringToMsgWin(PSTR psz, BOOL bUpdate)
  139. {
  140.     WriteBufferToMsgWin(psz, strlen(psz), bUpdate);
  141. }
  142.  
  143. /* Add message buffer (maybe part of a line) to the global status buffer
  144.  * that is the contents of the Message Window.
  145.  * Assumes that global data is unlocked when called.
  146.  */
  147. void WriteBufferToMsgWin(LPSTR pszBuffer, int nBufferLen, BOOL bUpdate)
  148. {
  149.     LPSTR   lpszT;              /* pointer into buffer                          */
  150.     HANDLE hStatusBufferTmp;
  151.     LPSTR lpGlobalBuffer;           /* pointer into global buffer               */
  152.     DWORD dwNewSize = dwStatusSize + (DWORD)nBufferLen;
  153.     int nIncrLines = 0;             /* incremental lines in buffer          */
  154.     int nIncompleteExistingLine = 0; /* add -1 if incomplete existing last line */
  155.     int nIncompleteAddedLine = 0;   /* add +1 if incomplete added last line     */
  156.     DWORD dwRequestedSize;          /* Size needed to hold all data. Can't
  157.                                        practically exceeded cchBufferMax.*/
  158.  
  159.     if (gfCancelDisplay)        /* if canceling display (in the middle of a lengthy operation) */
  160.         return;                    /* just discard data                            */
  161.  
  162.     if (!nBufferLen)    /* if no data       */
  163.         return;         /* just beat it     */
  164.  
  165.     /* count LF's in buffer to later add to total                       */
  166.     for (lpszT = pszBuffer; lpszT != NULL && (lpszT - pszBuffer) < nBufferLen; )
  167.     {
  168.         /* use memchr() for speed (?) considerations                    */
  169.         if (lpszT = _fmemchr(lpszT, '\n', (size_t)(nBufferLen - (lpszT - pszBuffer))))
  170.         {
  171.             nIncrLines++;   /* tally line found */
  172.             lpszT++;        /* point beyond LF for next pass */
  173.         }
  174.     }
  175.     if (dwNewSize > dwBufferSize)   /* if won't fit or 1st time */
  176.     {
  177.         /* Round up if necessary to nearest whole increment */
  178.         dwRequestedSize = ((dwNewSize + STATUS_INCREMENT - 1) / 
  179.                             STATUS_INCREMENT) * STATUS_INCREMENT;
  180.         if (hStatusBuffer)  /* if buffer exists, realloc */
  181.         {
  182.             if (dwRequestedSize <= cchBufferMax &&
  183.                     (hStatusBufferTmp = GlobalReAlloc(hStatusBuffer,
  184.                                 dwRequestedSize, GMEM_MOVEABLE)))
  185.             {
  186.                 /* successful re-allocation */
  187.                 hStatusBuffer = hStatusBufferTmp;
  188.                 dwBufferSize = dwRequestedSize;
  189.             }
  190.             else /* re-allocation failed, make last-ditch attempt! */
  191.             {
  192.                 FreeStatusLog();        /* free own buffers */
  193.                 if (MessageBox (hWndMain, szClearBufferMsg,
  194.                             "Note", MB_ICONINFORMATION | MB_OKCANCEL) == IDCANCEL)
  195.                     gfCancelDisplay = TRUE;
  196.  
  197.                 else /* no cancel */
  198.                     WriteBufferToMsgWin(pszBuffer, nBufferLen, bUpdate);
  199.  
  200.                 return;
  201.             }
  202.         }
  203.         else    /*